//和网络中接收连接相关的函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdint.h>
#include <stdarg.h>
#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>

#include "configure.h"
#include "macro.h"
#include "global.h"
#include "function.h"
#include "mysocket.h"

//建立新的连接
void MySocket::EventAccept(lpconnection_t old_connect) {
	struct sockaddr sock_addr;
	socklen_t sock_len;
	int err;
	int level;
	int accept_fd;//新建立的套接字
	static int use_accept4 = 1;
	lpconnection_t new_connect;

	sock_len = sizeof(sock_addr);

	do{
		if(use_accept4) {
			accept_fd = accept4(old_connect->fd, &sock_addr, &sock_len, SOCK_NONBLOCK);
		}
		else {
			accept_fd = accept(old_connect->fd, &sock_addr, &sock_len);
		}

		if(accept_fd == -1) {
			err = errno;
			if(err == EAGAIN) {
				return;
			}
			level = LOG_ALERT;
			if(err == ECONNABORTED) {
				level = LOG_ERR;
			}
			else if(err == EMFILE || err == ENFILE) {
				level = LOG_CRIT;
			}

			if(use_accept4 && err == ENOSYS) {
				use_accept4 = 0;
				continue;
			}
			if(err == ECONNABORTED) {
			
			}
			if(err == EMFILE||err == ENFILE) {
			
			}
			return;
		}
		//LogStderr(0,"accept成功!");
		if(online_user_count_ >= worker_connections_) {
			close(accept_fd);
			return;
		}
		if(connection_list_.size() > (worker_connections_ * 5)) {
			if(free_connection_list_.size() < worker_connections_) {
				close(accept_fd);
				return;
			}
		}
		new_connect = GetConnection(accept_fd);
		if(new_connect == NULL) {
			if(close(accept_fd) == -1) {
				LogErrorCore(LOG_ALERT, errno, "MySocket::EventAccept()中close(%d)失败!",accept_fd);
			}
			return;
		}

		memcpy(&new_connect->sock_addr, &sock_addr, sock_len);//拷贝客户端地址到连接对象
		if(!use_accept4) {
			if(SetNonblocking(accept_fd) == false) {
				CloseConnection(new_connect);
				return;
			}
		}

		new_connect->listening = old_connect->listening;
		new_connect->read_handler = &MySocket::ReadRequestHandler;
		new_connect->write_handler = &MySocket::WriteRequestHandler;
		if(EpollOperEvent(accept_fd, EPOLL_CTL_ADD, EPOLLIN|EPOLLRDHUP, 0, new_connect) == -1) {
			CloseConnection(new_connect);
			return;
		}
		if(if_kick_time_count_ == 1) {
			AddToTimerQueue(new_connect);
		}
		++online_user_count_;
		break;
	}while(1);
	return;
}
